<?php

namespace common\widgets\grid;

use Yii;
use yii\base\Arrayable;
use yii\base\InvalidConfigException;
use yii\base\Model;
use yii\base\Widget;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\Inflector;
use yii\i18n\Formatter;
use common\widgets\ConsoleActions;

/**
 * DetailView displays the detail of a single data [[model]].
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class DetailView extends \yii\widgets\DetailView {

    public $captionOptions = [];
    public $contentOptions = [];
    public $layoutOptions = [
        'class' => 'table-responsive',
    ];

    /**
     * @var array the HTML attributes for the container tag of this widget. The `tag` option specifies
     * what container tag should be used. It defaults to `table` if not set.
     * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
     */
    public $options = ['class' => 'table table-hover'];

    /**
     * @var boolean whether to show the grid view if [[dataProvider]] returns no data.
     */
    public $theader = false;

    /**
     * @var boolean whether to show the grid view if [[dataProvider]] returns no data.
     */
    public $showOnEmpty = true;

    /**
     * @var boolean whether to show the grid view if [[dataProvider]] returns no data.
     */
    public $showConsoles = false;

    /**
     * @var string the HTML display when the content of a cell is empty.
     * This property is used to render cells that have no defined content,
     * e.g. empty footer or filter cells.
     *
     * Note that this is not used by the [[DataColumn]] if a data item is `null`. In that case
     * the [[\yii\i18n\Formatter::nullDisplay|nullDisplay]] property of the [[formatter]] will
     * be used to indicate an empty data value.
     */
    public $emptyCell = '&nbsp;';

    /**
     * Initializes the detail view.
     * This method will initialize required property values.
     */
    public function init() {
        if ($this->model !== null) {
            if ($this->formatter === null) {
                $this->formatter = Yii::$app->getFormatter();
            } elseif (is_array($this->formatter)) {
                $this->formatter = Yii::createObject($this->formatter);
            }
            if (!$this->formatter instanceof Formatter) {
                throw new InvalidConfigException('The "formatter" property must be either a Format object or a configuration array.');
            }
            $this->normalizeAttributes();
        }
        $id = ArrayHelper::remove($this->options, 'id', $this->getId());
        if ($this->layoutOptions !== false) {
            $this->layoutOptions['id'] = $id;
        } else {
            $this->options['id'] = $id;
        }
        $this->trigger(self::EVENT_INIT);
    }

    /**
     * Renders the detail view.
     * This is the main entry of the whole detail view rendering.
     */
    public function run() {
        $view = $this->getView();
        DetailViewAsset::register($view);
        $content = $this->renderItems($this->options);
        if ($this->layoutOptions !== false) {
            $tag = ArrayHelper::remove($this->layoutOptions, 'tag', 'div');
            return Html::tag($tag, $content, $this->layoutOptions);
        }
        return $content;
    }

    protected function renderItems($options = []) {
        $content = array_filter([
            $this->renderTheader(),
            $this->renderTbody()
        ]);
        $tag = ArrayHelper::remove($options, 'tag', 'table');
        Html::addCssClass($options, 'detail-view');
        return Html::tag($tag, implode("\n", $content), $options);
    }

    protected function renderEmpty() {
        if (!$this->showOnEmpty) {
            return null;
        }
        return "<tbody><tr><td colspan='2' class='empty'>{$this->emptyCell}</td></tr></tbody>";
    }

    protected function renderTheader() {
        if ($this->theader === false) {
            return null;
        }
        return "<thead><tr><th colspan='2'>{$this->theader}</th></tr></thead>";
    }

    protected function renderTbody() {
        if (!$this->model) {
            return $this->renderEmpty();
        }
        $rows = [];
        $i = 0;
        foreach ($this->attributes as $attribute) {
            $rows[] = $this->renderAttribute($attribute, $i++);
        }
        if ($this->showConsoles === true && $this->model->hasMethod('getConsoles')) {
            $rows[] = $this->renderAttributeConsoles($i++);
        }
        return "<tbody>\n" . implode("\n", $rows) . "\n</tbody>";
    }

    protected function renderAttributeConsoles($index) {
        $consoles = ConsoleActions::widget([
            'options' => ['class' => 'btn-group btn-group-devided'],
            'items' => $this->model->getConsoles()
        ]);
        return $this->renderAttribute([
            'attribute' => 'consoles',
            'label' => '操作',
            'format' => 'raw',
            'value' => $consoles
        ], $index);
    }

    /**
     * Renders a single attribute.
     * @param array $attribute the specification of the attribute to be rendered.
     * @param int $index the zero-based index of the attribute in the [[attributes]] array
     * @return string the rendering result
     */
    protected function renderAttribute($attribute, $index) {
        if (is_string($this->template)) {
            $captionOptions = Html::renderTagAttributes(ArrayHelper::getValue($attribute, 'captionOptions', $this->captionOptions));
            $contentOptions = Html::renderTagAttributes(ArrayHelper::getValue($attribute, 'contentOptions', $this->contentOptions));
            return strtr($this->template, [
                '{label}' => $attribute['label'],
                '{value}' => $this->formatter->format($attribute['value'], $attribute['format']),
                '{captionOptions}' => $captionOptions,
                '{contentOptions}' => $contentOptions,
            ]);
        }
        return call_user_func($this->template, $attribute, $index, $this);
    }

}
